1.获取上传的文件

  • request.FILES.get('file_name')

def upload_file(request):
    if request.method == 'POST':
        file_obj = request.FILES.get('img_file')  # 获取上传文件
    return render(request, 'upload_file.html')

2.获取上传文件的文件名+后缀

  • request.FILES.get('file_name').name

def upload_file(request):
    if request.method == 'POST':

        file_obj = request.FILES.get('img_file')
        file_name = file_obj.name  # 获取上传文件的文件名+后缀
# 等价于
        file_name = request.FILES.get('img_file').name  # 获取上传文件的文件名+后缀

    return render(request, 'upload_file.html')

3.获取上传文件的大小

  • request.FILES.get('file_name').size

def upload_file(request):
    if request.method == 'POST':

        file_obj = request.FILES.get('img_file')
        file_size = file_obj.size  # 获取上传文件的大小
     # 等价于
        file_size = request.FILES.get('img_file').size  # 获取上传文件的大小

    return render(request, 'upload_file.html')

4..read()

  • 一次性读取整个上传文件的内容,这个方法只适合于小文件

  • 语法: request.FILES.get('file_name').read()

def upload_file(request):
    if request.method == 'POST':

        file_obj = request.FILES.get('img_file')  # 获取上传文件
        file_name = file_obj.name  # 获取上传文件的文件名+后缀
        with open(file_name, 'wb') as f:
            all_data = file_obj.read()  # 一次性读取整个上传文件的内容
            f.write(all_data)

        return HttpResponse('上传成功')
    return render(request, 'upload_file.html')

5..chunks()

  • 按块返回上传文件的内容,通过在for循环中进行迭代,可以将大文件按照块写入服务器中

  • 注意: 这个方法和直接循环文件对象是差不多的,不同在于.chunks()方法是一块一块的读取数据,而直接循环文件对象是一行一行的读取数据

  • 语法: request.FILES.get('file_name').chunks()

def upload_file(request):
    if request.method == 'POST':

        file_obj = request.FILES.get('img_file')  # 获取上传文件
        file_name = file_obj.name  # 获取上传文件的文件名+后缀
        with open(file_name, 'wb') as f:
            for line in file_obj.chunks():  # 一块一块的读取并且写入
                f.write(line)

        return HttpResponse('上传成功')
    return render(request, 'upload_file.html')

6..multiple_chunks(chunk_size=None)

  • 根据上传文件的大小,返回True或者False,当上传文件大于2.5M(默认为2.5M,可以调整)时,该方法返回True,否则返回False

  • 可以根据.multiple_chunks()方法来选择选用.read()方法读取还是采用.chunks()方法

  • 语法: request.FILES.get('file_name').multiple_chunks()

def upload_file(request):
    if request.method == 'POST':

        file_obj = request.FILES.get('img_file')  # 获取上传文件
        file_name = file_obj.name  # 获取上传文件的文件名+后缀
        with open(file_name, 'wb') as f:
            if file_obj.multiple_chunks():  # 判断上传文件是否超过了2.5M
                for line in file_obj.chunks():  # 一块一块的读取并且写入
                    f.write(line)
            else:
                all_data = file_obj.read()  # 一次性读取整个上传文件的内容
                f.write(all_data)

        return HttpResponse('上传成功')
    return render(request, 'upload_file.html')

7.使用form表单上传文件的例子

form_upper_bunken.rar

  • 注意: 如果表单中带有要上传的文件,那么一定要修改表单中的 enctype="multipart/form-data"

  • enctype 参数说明:

    • application/x-www-form-urlencoded -> 一般用于提交不带文件的表单 -> 默认值
    • multipart/form-data -> 一般用于提交带文件的表单

  • enctype 参数 和 Content-Type 的关系

    • enctype 参数其实就是修改请求头中的 Content-Type 参数,而 Content-Type 参数就是让浏览器告诉服务器这次请求数据的格式是什么
    • Content-Type参数的默认值和enctype参数一样都是 urlencoded

  • 注意事项: 

    • 如果表单中没有上传文件,那么使用默认值提交就可以(即: 无需修改enctype参数),Django会将表单提交过来的数据放到 request.GET/POST 中

    • 如果表单中有上传文件,那么一定要修改表单中的 enctype="multipart/form-data",Django会将上传文件以外的数据放到 request.GET/POST 中,将上传文件放到 reques.FILES 中

    • 如果表单中有上传文件,且没有修改 enctype="multipart/form-data",Django会将表单提交过来的数据放到 request.GET/POST 中,那么通过 request.GET/POST.get('file_name') 获取到的只是上传文件的文件名+后缀,不是一个文件对象

# views.py

def upload_file(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        file_obj = request.FILES.get('img_file')  # 获取上传文件
        file_name = file_obj.name  # 获取上传文件的文件名+后缀
        with open(file_name, 'wb') as f:
# for line in file_obj:  # 一行一行的读取并且写入
            # 等价于
            for line in file_obj.chunks():  # 一块一块的读取并且写入
                f.write(line)
        return HttpResponse('上传成功')
    return render(request, 'upload_file.html')

# xxx.html

<form action="" method=post enctype="multipart/form-data">
    {% csrf_token %}
    <p><input type="text" name="username" id="" placeholder="用户名"></p>
    <p><input type="password" name="password" id="" placeholder='密码'></p>
    <p><input type="file" name="img_file" id=""></p>
    <input type="submit" value="提交">
</form>

8.将上传文件保存到 media 文件夹中

media_upper_bunken.rar

  • 将上传文件保存到 media 文件夹中的前提是配置了media

  • 使用 settings.py 中 media 文件夹路径的配置项进行上传文件保存路径的拼接

# views.py

from django.shortcuts import render, HttpResponse
from upper_bunken import settings
import os


def upload_file(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        file_obj = request.FILES.get('img_file')  # 获取上传文件
        file_name = file_obj.name  # 获取上传文件的文件名+后缀

path = os.path.join(settings.MEDIA_ROOT, file_name)  # 使用 settings.py 中的 media 配置项的路径进行拼接
 # 等同于
        # path = 'media/' + file_name # 不建议这么写:
   # 一、因为当 media 文件夹被改动了,那么这里的路径也需要改动,但是使用上面的方法就无需改动,只要修改 settings.py 中的 media 配置项就可以了
   # 二、因为在 linux 中路径分割符是 \,而不是/,如果在linux下运行有可能会报错

        with open(path, 'wb') as f:
# for line in file_obj:  # 一行一行的读取并且写入
            # 等价于
            for line in file_obj.chunks():  # 一块一块的读取并且写入
                f.write(line)

        return HttpResponse('上传成功')

    return render(request, 'upload_file.html')

# xxx.html

<form action="" method=post enctype="multipart/form-data">
    {% csrf_token %}
    <p><input type="text" name="username" id="" placeholder="用户名"></p>
    <p><input type="password" name="password" id="" placeholder='密码'></p>
    <p><input type="file" name="img_file" id=""></p>
    <input type="submit" value="提交">
</form>

8.使用Ajax上传文件的例子

  • 注意事项:Ajax上传文件的注意事项和Form表单差不多,都需要通过修改某些参数后才能进行提交

# views.py

def upload_file(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        file_obj = request.FILES.get('img_file')  # 获取上传文件
        file_name = file_obj.name  # 获取上传文件的文件名+后缀
        with open(file_name, 'wb') as f:
# for line in file_obj:  # 一行一行的读取并且写入
            # 等价于
            for line in file_obj.chunks():  # 一块一块的读取并且写入
                f.write(line)
        return HttpResponse('上传成功')
    return render(request, 'upload_file.html')

  • 写法一 -> 推荐使用

ajax1_upper_bunken.rar

# xxx.html

<div>
    {% csrf_token %}
    <p><input type="text" name="username" id="username" placeholder="用户名"></p>
    <p><input type="password" name="password" id="password" placeholder='密码'></p>
    <p><input type="file" name="img_file" id="img_file"></p>
    <button id="btn">提交</button>
</div>

<script type="text/javascript">
    $(function () {
        $('#btn').click(function () {
 // 将数据添加到 FormData 里面
            var formData = new FormData();
            formData.append('username', $('#username').val());
            formData.append('password', $('#password').val());
            formData.append('csrfmiddlewaretoken', $("[name='csrfmiddlewaretoken']").val());
            formData.append('img_file', $('#img_file')[0].files[0]);

            $.ajax({
                url: '/upload_file/',
                type: "POST",
processData: false,  // 告诉jQuery不要去处理发送的数据
                contentType: false,  // 告诉jQuery不要去设置Content-Type请求头
data: formData,
                success: function (data) {
                    console.log(data)
                }
            })
        })
    })
</script>

  • 写法二

    • 有点问题: 就算Ajax设置了POST请求,但是在发送的时候还是GET请求

ajax2_upper_bunken.rar

# xxx.html

<form id="upload-form">
    {% csrf_token %}
    <p><input type="text" name="username" id="username" placeholder="用户名"></p>
    <p><input type="password" name="password" id="password" placeholder='密码'></p>
    <p><input type="file" name="img_file" id="img_file"></p>
    <button id="btn">提交</button>
</form>

<script type="text/javascript">
    $(function () {
        $('#btn').click(function () {
// 将数据添加到 FormData 里面
            var form = $('#upload-form')[0];
            var formData = new FormData(form);

            $.ajax({
                url: '/upload_file/',
                type: "POST",
processData: false,  // 告诉jQuery不要去处理发送的数据
                contentType: false,  // 告诉jQuery不要去设置Content-Type请求头
                data: formData,
                success: function (data) {
                    console.log(data)
                }
            })
        })
    })
</script>